package com.hongdee.crm.task.service.impl;

import com.hongdee.annotation.MethodComment;
import com.hongdee.common.util.DateUtils;
import com.hongdee.common.util.StringUtil;
import com.hongdee.crm.Constant;
import com.hongdee.crm.task.dao.IBcMaintainTypeTaskDao;
import com.hongdee.crm.task.dao.ITCrmCarMaintainTaskDao;
import com.hongdee.crm.task.dao.ITCrmTaskDao;
import com.hongdee.crm.task.dto.MainTainDTO;
import com.hongdee.crm.task.entity.TCrmTask;
import com.hongdee.crm.task.service.ITCrmCarMaintainTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 名  称: TCrmCarMaintainTaskServiceImpl
 * 类  型: class
 * 描  述: 首保任务类
 * 路  径: com.hongdee.crm.task.service.impl
 * 作  者: wangshuai
 * 日  期:2017/2/28 10:23
 */
@Component("firstCarMaintainTaskService")
public class TCrmCarMaintainTaskServiceImpl implements ITCrmCarMaintainTaskService{

    @Autowired
    private ITCrmCarMaintainTaskDao carMaintainTaskDao;
    @Autowired
    private ITCrmTaskDao taskDao;

    @Autowired
    private IBcMaintainTypeTaskDao bcMaintainTypeTaskDao;


    private final String YYYYMMDD="yyyy-MM-dd";
    private final int LIMIT = 1000;
    private final String MAINTAINNAME="首保";

    private final String BY_CODE="by";
    private final String SB="sb";
    private final String MBY="mby";
    private final String TXTS="txts";
    private final String JSYF="jsyf";
    private final String MBR="mbr";

    private MainTainDTO mbyMainTainDTO;
    private MainTainDTO mbrMainTainDTO;



    /**
     * 车辆首保
     * sql查询规则：
     * 1、根据当前时间向前推六个月，查询质保时间大于六个月的时间；
     * 2、排除工单中已经做过首保的车辆
     * 执行步骤：
     * 1、根据t_bc_param_set查询出设置首保类型的公司
     * 2、根据公司ID取出配置的首保相关信息
     * 3、查询出公司所配置的首保关系的维修项目
     * 4、根据sql查询出相应的车辆信息
     * 5、遍历车辆信息，先根据车辆质保信息生成其实目标日信息
     * 6、将目标日时间与当前时间对比，如目标日时间大于当前时间，则执行目标日时间；如目标日时间小于当前时间，则执行目标月时间
     * 7、判断目标月（目标日）时间是否在下月1号至下下月1号零点之间
     * 8、判断目标月（目标日）任务是否存在，如存在则跳出循环，如不存在生个TCrmTask实体类
     * 9、批量保存
     * @throws Exception
     */
//    @Scheduled(cron="0 30 2 28 * ? *") //每月28日2点30执行
    @Override
    @MethodComment(name = "首保 首保月定时任务")
    public Integer carMaintainQuartz() throws Exception {
        Integer nums=0;
        List<Map<String,Object>> companyList=carMaintainTaskDao.findCompanyList(SB+"_"+MBY,SB+"_"+MBR);
        //遍历公司信息
        for(Map<String,Object> map:companyList){
            //取得公司ID
            String compnayId=String.valueOf(map.get("company_id"));
            //根据公司ID 判断是否有首保任务 首保月任务
            int num=this.carMaintain(compnayId,"","");
            nums+=num;
        }
        return nums;
    }

    @Override
    public Integer carMaintain(String compnayId,String startTime,String endTime) throws Exception {
        long nowTime=MaintainUtil.getNowTime();
        this.getMainTainParamInfo(compnayId);
        long maintainTime=DateUtils.addMonthLongTime(nowTime,-6);
        int nums=0;
        nums+=findCarFirstMaintain(maintainTime, compnayId,nowTime,startTime,endTime,mbrMainTainDTO.getCode());
        nums+=findCarFirstMaintain(maintainTime, compnayId,nowTime,startTime,endTime,mbyMainTainDTO.getCode());
        return nums;
    }

    /**
     * 查询首保车辆信息
     * @param nowTime
     * @param companyId
     * @throws Exception
     */
    private Integer findCarFirstMaintain(long maintainTime,String companyId,long nowTime,String startTime,String endTime,String code)throws Exception{
        Integer nums=0;
        int start = 0;
        List<Map<String,Object>> maintainTypeList=bcMaintainTypeTaskDao.findSetMaintainType(companyId,SB);
        if(maintainTypeList!=null) {
            while (true) {
                //生成sql相关
                StringBuffer sqlStr = new StringBuffer();
                List<Object> paramLists = new ArrayList<>();
                paramLists.add(maintainTime);
                this.analyCompalyToSql(maintainTypeList, companyId, sqlStr, paramLists,code);
                paramLists.add(start * LIMIT);
                paramLists.add(LIMIT);
                //获得要首保或首保月的车辆数据
                List<Map<String, Object>> lists = carMaintainTaskDao.carMaintainList(sqlStr.toString(),paramLists);
                //退出判断
                if (lists == null) {
                    start = 0;
                    break;
                } else {
                    //解析车辆信息 生成首保任务
                    List<TCrmTask> tasks = this.analyCars(lists, nowTime,startTime,endTime,code);
                    if (tasks.size() > 0) {
                        nums+=tasks.size();
                        long start1 = System.currentTimeMillis();
                        carMaintainTaskDao.insertMaintailLists(tasks);
                        long end = System.currentTimeMillis();
                        System.out.println("运行时间：" + (end - start1) + "毫秒");//应该是end - start
                    }
                }
                start++;
            }
        }
        return nums;
    }


    /**
     * 解析车辆信息 生成任务实体类
     * @param lists
     * @param nowTime
     * @return
     * @throws Exception
     */
    private List<TCrmTask> analyCars(List<Map<String, Object>> lists,long nowTime,String startTime,String endTime,String code)throws Exception{
        List<TCrmTask> list=new ArrayList<>();
        for (Map<String, Object> map : lists) {
            //取出质保/'时间
//            Object guaranteeDateO = map.get("guarantee_start_date");
            //取出销售日期，根据销售日期执行首保任务 //改为取销售日期 2017-05-09
            Object guaranteeDateO = map.get("buy_date");
            String plateNum="";
            if(map.get("plate_num")==null){
                String vin=String.valueOf(map.get("vin"));
                plateNum=vin.substring(vin.length()-6,vin.length());
                map.put("plate_num",plateNum);
            }
            if(String.valueOf(map.get("plate_num")).equals("无牌照")){
                String vin=String.valueOf(map.get("vin"));
                plateNum=vin.substring(vin.length()-6,vin.length());
                map.put("plate_num",plateNum);
            }
            if (guaranteeDateO != null) {
                long guaranteeDate = Long.parseLong(String.valueOf(guaranteeDateO));
                String carId=String.valueOf(map.get("id"));
                switch (code){
                    case "sb_mbr":
                        this.saveSbMbrTask(nowTime,startTime,endTime,map,guaranteeDate,list);
                        break;
                    case "sb_mby":
                        this.saveSbMbyTask(nowTime,startTime,endTime,map,guaranteeDate,list);
                        break;
                }

//
//
//
//                //计算时间，返回结果sbflag true首保日 false 月，tasktime任务提醒时间 byTime理论上保养最后时间点
//                List<Map<String,Object>> taskMapList = this.firstMaintainTime(guaranteeDate, nowTime,carId);
//                for (Map<String,Object> taskMap:taskMapList) {
//
//                    long taskTime=Long.parseLong(String.valueOf(taskMap.get("taskTime")));
//                    long byTime=Long.parseLong(String.valueOf(taskMap.get("byTime")));
//                    boolean sbflag=Boolean.parseBoolean(String.valueOf(taskMap.get("sb")));
//                    //判断日期是否在下月之中也就是下月1号至下下月1号，如当前月3月，那么日期需要在4.1至5.1之间
//                    boolean flag = DateUtils.checkTime(byTime,nowTime);
//                    if(!"".equals(startTime) && !"".equals(endTime)){
//                        flag=DateUtils.checkTime(byTime,startTime,endTime);
//                    }
//                    if (flag) {
//                        String companyId=String.valueOf(map.get("company_id"));
//
//                        //保存任务之前需要判断
//                        if(sbflag){
//                            //首保日任务
//                            //根据车辆 查看首保日任务是否存在
//                            boolean taskFlag=this.checkSbTask(companyId,carId,mbrMainTainDTO.getCode());
//                            if(taskFlag){//已经存在，则直接跳出循环
//                                continue;
//                            }
//                        }else{
//                            //首保月任务 无需查询是否存在首保日任务
//                            boolean taskFlag=this.checkSbTask(companyId,carId,mbyMainTainDTO.getCode());
//                            if(taskFlag){//已经存在，则直接跳出循环
//                                continue;
//                            }
//                        }
//                            //2、如果存在首保存日任务 则创建首保月任务
//                        TCrmTask task = this.saveTask(map, taskTime, byTime, sbflag, guaranteeDate);
//                        list.add(task);
//                    }
//                }
            }
        }
        return list;
    }

    /**
     * 首保月任务，计算执行日期，生成首保任务
     * @param nowTime
     * @param startTime
     * @param endTime
     * @param map
     * @param guaranteeDate
     * @param list
     * @throws Exception
     */
    private void saveSbMbrTask(Long nowTime,String startTime,String endTime,
                               Map<String, Object> map,long guaranteeDate,List<TCrmTask> list) throws Exception {
        if(mbrMainTainDTO.getJsyfNums()!=null) {
            //任务时间
            long taskTime = DateUtils.addMonthLongTime(guaranteeDate, +mbrMainTainDTO.getJsyfNums().intValue());
            //提醒 时间
            long byTime = DateUtils.addDayLongTime(taskTime, -mbrMainTainDTO.getTxtsNums().intValue());
            String carId = String.valueOf(map.get("id"));
            //判断是否在下月1日与下下月1日之间执行
            boolean flag = DateUtils.checkTime(byTime, nowTime);
            if (!"".equals(startTime) && !"".equals(endTime)) {
                //判断是否在指定日期执行
                flag = DateUtils.checkTime(byTime, startTime, endTime);
            }
            if (flag) {
                String companyId = String.valueOf(map.get("company_id"));
                //首保日任务
                //根据车辆 查看首保日任务是否存在
                boolean taskFlag = this.checkSbTask(companyId, StringUtil.formatEmpty(map.get("vin")),carId, mbrMainTainDTO.getCode());
                if (!taskFlag) {
                    String tpl = "%s车，车主[%s],首保提醒!保修开始时间%s.";
                    TCrmTask task = this.saveTask(map, byTime, tpl, guaranteeDate, mbrMainTainDTO.getCode());
                    list.add(task);
                }
            }
        }
    }

    /**
     * 首保月任务，计算执行日期，生成首保月任务
     * @param nowTime
     * @param startTime
     * @param endTime
     * @param map
     * @param guaranteeDate
     * @param list
     * @throws Exception
     */
    private void saveSbMbyTask(Long nowTime,String startTime,String endTime,
                               Map<String, Object> map,long guaranteeDate,List<TCrmTask> list) throws Exception {
        if(mbyMainTainDTO.getJsyfNums()!=null) {
            //任务时间
            long sixMonthTime = DateUtils.addMonthLongTime(guaranteeDate, +mbyMainTainDTO.getJsyfNums().intValue());
            //提醒 时间
            long byTime = DateUtils.addDayLongTime(sixMonthTime, -mbyMainTainDTO.getTxtsNums().intValue());

            boolean flag = DateUtils.checkTime(byTime, nowTime);
            String carId = String.valueOf(map.get("id"));
            if (!"".equals(startTime) && !"".equals(endTime)) {
                flag = DateUtils.checkTime(byTime, startTime, endTime);
            }
            if (flag) {
                String companyId = String.valueOf(map.get("company_id"));
                //首保月任务 无需查询是否存在首保日任务 true已经存在 false不存在
                boolean taskFlag = this.checkSbTask(companyId, StringUtil.formatEmpty(map.get("vin")), carId, mbyMainTainDTO.getCode());
                if (!taskFlag) {//存在，直接生成
                    String tpl = "%s车，车主[%s],首保提醒!保修开始时间%s.[目标月]";
                    TCrmTask task = this.saveTask(map, byTime, tpl, guaranteeDate, mbyMainTainDTO.getCode());
                    list.add(task);
                }
            }
        }
    }




    /**
     * 保存首保类任务
     * @param mTmp
     * @throws Exception
     */
    private TCrmTask saveTask(Map<String,Object> mTmp,long byTime,String tpl,long guaranteeDate,String code) throws Exception {
        TCrmTask task = new TCrmTask();
        task.setCreateTime(new Date().getTime());
        task.setVIN(mTmp.get("vin").toString());
        task.setCarId(mTmp.get("id").toString());
        task.setPlateNum(mTmp.get("plate_num").toString());
        task.setCompanyId(mTmp.get("company_id").toString());
        task.setLinkman(com.hongdee.common.util.StringUtil.formatNull(mTmp.get("owner_name")));
        if(mTmp.get("owner_tel")!=null) {
            task.setLinkphone(mTmp.get("owner_tel").toString());
        }
        task.setExpectDate(DateUtils.formatLongTime(byTime,YYYYMMDD));
        task.setStatus("0");
        task.setIsBack("0");
        task.setTypePCode(BY_CODE);
        StringBuffer contentStr=new StringBuffer();
        String guaranteeDateStr=DateUtils.formatLongTime(guaranteeDate,YYYYMMDD);
        //首保日
        task.setTypeCode(code);
        String tplStr=String.format(tpl,task.getPlateNum(),task.getLinkman(),guaranteeDateStr);
        contentStr.append(tplStr);
        task.setContent(contentStr.toString());
        return task;
    }





    /**
     * 检测任务是否已经存在，如果已经存在返回true，未存在返回false
     * @param companyId
     * @param carId
     * @param code
     * @return
     * @throws Exception
     */
    private boolean checkSbTask(String companyId,String vin,String carId,String code) throws Exception {
        List<Map<String,Object>> lists=taskDao.findTaskByCarIdAndVin(companyId,vin,carId,BY_CODE,code);
        if(lists!=null){
            if(lists.size()>0){
                return true;
            }
        }
        return false;
    }
//    /**
//     * 保存首保类任务
//     * @param mTmp
//     * @param taskTime
//     * @throws Exception
//     */
//    private TCrmTask saveTask(Map<String,Object> mTmp,long taskTime,long byTime,boolean sbflag,long guaranteeDate) throws Exception {
//        TCrmTask task = new TCrmTask();
//        task.setVIN(mTmp.get("vin").toString());
//        task.setCarId(mTmp.get("id").toString());
//        task.setPlateNum(mTmp.get("plate_num").toString());
//        task.setCompanyId(mTmp.get("company_id").toString());
//        task.setLinkman(mTmp.get("contact_name").toString());
//        if(mTmp.get("contact_phone")!=null) {
//            task.setLinkphone(mTmp.get("contact_phone").toString());
//        }
//        task.setExpectDate(DateUtils.formatLongTime(byTime,YYYYMMDD));
//        task.setStatus("0");
//        task.setTypePCode(BY_CODE);
//        StringBuffer contentStr=new StringBuffer();
//        String byTimeStr=DateUtils.formatLongTime(byTime,YYYYMMDD);
//        String taskTimeStr=DateUtils.formatLongTime(taskTime,YYYYMMDD);
//        String guaranteeDateStr=DateUtils.formatLongTime(guaranteeDate,YYYYMMDD);
//        if(sbflag){
//            //首保日
//            task.setTypeCode(mbrMainTainDTO.getCode());
//            contentStr.append(task.getPlateNum()+"车，车主["+task.getLinkman()+"],首保提醒!保修开始时间"+guaranteeDateStr+".");
////            contentStr.append(task.getPlateNum()+"的车主["+task.getLinkman()+"]首保养提醒时间为："+taskTimeStr+"首保建议时间："+byTimeStr+";联系方式:"+task.getLinkphone());
//        }else{
//            //首保月
//            task.setTypeCode(mbyMainTainDTO.getCode());
//            contentStr.append(task.getPlateNum()+"车，车主["+task.getLinkman()+"],首保提醒!保修开始时间"+guaranteeDateStr+".[目标月]");
////            contentStr.append(task.getPlateNum()+"的车主["+task.getLinkman()+"]首保养提醒时间为："+taskTimeStr+"首保最终截止时间为："+byTimeStr+";联系方式:"+task.getLinkphone());
//        }
//
//
//        task.setContent(contentStr.toString());
//        return task;
//    }

//    /**
//     * 计算首保时间
//     * @param guaranteeDate
//     * @param nowTime
//     * @return
//     * @throws Exception
//     */
//    private List<Map<String,Object>> firstMaintainTime(long guaranteeDate,long nowTime,String carId) throws Exception {
//
//        List<Map<String,Object>> list=new ArrayList<>();
//        long sixMonthTime=DateUtils.addMonthLongTime(guaranteeDate,+mbyMainTainDTO.getJsyfNums().intValue());
//        long threeMonthTime=DateUtils.addMonthLongTime(guaranteeDate,+mbrMainTainDTO.getJsyfNums().intValue());
//
//        Map<String,Object> mbyMap=new HashMap<>();
//
//        mbyMap.put("sb",false);
//        mbyMap.put("byTime",DateUtils.addDayLongTime(sixMonthTime,-mbyMainTainDTO.getTxtsNums().intValue()));
//        mbyMap.put("taskTime",sixMonthTime);
//        list.add(mbyMap);
//
//
//        Map<String,Object> mbrMap=new HashMap<>();
//        mbrMap.put("sb",true);
//        mbrMap.put("byTime",DateUtils.addDayLongTime(threeMonthTime,-mbrMainTainDTO.getTxtsNums().intValue()));
//        mbrMap.put("taskTime",threeMonthTime);
//        list.add(mbrMap);
//        return list;
//    }

    /**
     * 根据公司所设定的维修项目 生成sql
     * @param maintainTypeList
     * @param companyId
     * @param sqlStr
     * @param paramLists
     */
    private void analyCompalyToSql(List<Map<String,Object>> maintainTypeList,String companyId,StringBuffer sqlStr,List<Object> paramLists,String code){
        sqlStr.append("SELECT car.vin, car.id, car.contact_name, car.contact_phone, car.plate_num, car.said, car.guarantee_start_date, car.company_id" +
                ",car.buy_date,car.owner_name,car.owner_tel,car.owner_phone " +
                "FROM t_crm_car car WHERE " +
//                "guarantee_start_date >= ? " +
                "car.buy_date>= ?  "+
                "AND car.company_id = ? " +
//                "AND car.guarantee_start_date IS NOT NULL " +
                "AND car.buy_date IS NOT NULL " +
//                "AND car.vin='LSVD76A44HN026291' " +
                "AND car.from_company='是'  " +
                "AND NOT EXISTS ( " +
                "SELECT * FROM t_crm_car_workorder " +
                "WHERE wx_type IN ('首保', '二保', '定保') " +
                "AND car.vin = vin " +
                "AND car.company_id=company_id " +
                ")  " );
        Constant.REMIND_CLOSE_SQL(sqlStr,BY_CODE,code,"car");
//        sqlStr.append("AND NOT EXISTS ( " +
//                "SELECT * FROM t_crm_car_remindclose cl WHERE cl.user_carid = car.id ) " );
        sqlStr.append("LIMIT ?,?");
        paramLists.add(companyId);
    }

    /**
     * 解析参数信息 生成相应的DTO类
     * @param companyId
     * @throws Exception
     */
    private void getMainTainParamInfo(String companyId)throws Exception{
        //遍历
//        for (Map<String,Object> map:params) {
//            String mapCode=String.valueOf(map.get("code"));
//            if((SB+"_"+MBY).equals(mapCode)){
        //根据code值 查询其下属信息
        List<Map<String,Object>> mbyList=carMaintainTaskDao.findCompanyParamList(companyId,SB+"_"+MBY);
        if(mbyList!=null) {
            mbyMainTainDTO = MainTainDTO.analyParams(mbyList, SB + "_" + MBY + "_" + TXTS, SB + "_" + MBY + "_" + JSYF, SB + "_" + MBY);
            mbyMainTainDTO.setCode(SB + "_" + MBY);
            this.setMbyMainTainDTO(mbyMainTainDTO);
        }
//            }else if((SB+"_"+MBR).equals(mapCode)){
        List<Map<String,Object>> mbrList=carMaintainTaskDao.findCompanyParamList(companyId,SB+"_"+MBR);
        if(mbrList!=null) {
            mbrMainTainDTO = MainTainDTO.analyParams(mbrList, SB + "_" + MBR + "_" + TXTS, SB + "_" + MBR + "_" + JSYF, SB + "_" + MBR);
            mbrMainTainDTO.setCode(SB + "_" + MBR);
            this.setMbrMainTainDTO(mbrMainTainDTO);
        }
//            }
//        }
    }

    public MainTainDTO getMbyMainTainDTO() {
        return mbyMainTainDTO;
    }

    public void setMbyMainTainDTO(MainTainDTO mbyMainTainDTO) {
        this.mbyMainTainDTO = mbyMainTainDTO;
    }

    public MainTainDTO getMbrMainTainDTO() {
        return mbrMainTainDTO;
    }

    public void setMbrMainTainDTO(MainTainDTO mbrMainTainDTO) {
        this.mbrMainTainDTO = mbrMainTainDTO;
    }

}
